// import { Settings } from "http2";
// import { data } from "jquery";
// import { version } from "os";

namespace study4_01 {

    // keyof 用于获取某个对象类型的所有键的联合类型
    // 用于获取某个对象类型的所有键的集合，并将其作为一个联合类型返回
    // keyof 将一个接口对象的全部属性取出来变成联合类型
    type Person = {
        name: string
        age: number
        isEmployed: boolean
    }

    type PersonKeys = keyof Person; // PersonKeys 的类型是  "name" | "age" | "isEmployed"


    let p: PersonKeys;

    p = 'name'
    p = 'age'
    p = 'isEmployed'

    // 示例：使用p来访问Person对象的属性
    let person: Person = {
        name: '崔梦娇',
        age: 22,
        isEmployed: true
    }

    // 假设我们有一个函数来获取 Person 对象的某个属性
    function getProperty<K extends keyof Person>(person: Person, key: K): Person[K] {
        return person[key]
    }

    // 使用 p 变量来获取属性值
    let nameCui: string = getProperty(person, 'name')
    let ageCui: number = getProperty(person, 'age')
    let isEmployedCui: boolean = getProperty(person, 'isEmployed')
    console.log(nameCui, ageCui, isEmployedCui); // 崔梦娇 22 true


    // 应用场景

    // 1、约束函数的参数类型
    //  约束函数的参数，确保参数是对象的某个键值
    function getProperty1<T, K extends keyof T>(obj: T, key: K): T[K] {
        return obj[key]
    }

    let person1 = {
        name: '志超',
        age: 21
    }

    let nameZhi: string = getProperty1(person1, "name")
    let ageZhi: number = getProperty1(person1, "age")
    console.log(nameZhi, ageZhi); // 志超 21




    // 2、动态属性访问
    // keyof 结合泛型和索引类型，可以让ts编译时推断出对象属性的类型，提升类型安全性
    type Config = {
        apiEndpoint: string
        timeout: number
    }

    function updateConfig<T, K extends keyof T>(config: T, key: K, value: T[K]): T[K] {
        config[key] = value
        return config[key]
    }

    // 使用示例
    let config: Config = {
        apiEndpoint: 'api结束点',
        timeout: 3000
    }

    let api: string = updateConfig(config, "apiEndpoint", '结束点')
    let time: number = updateConfig(config, "timeout", 5000)
    console.log(api, time); // 结束点 5000
    console.log(config); // { apiEndpoint: '结束点', timeout: 5000 }




    // 3、遍历对象的属性
    // 可以使用keyof结合 in关键字，来遍历对象类型的所有键
    type Person2 = {
        name: string
        age: number
        isEmployed: boolean
    };

    type PersonPartial = {
        [K in keyof Person]?: Person2[K]
    };

    let partial: PersonPartial = {
        name: '林萃',
        age: 20
    }
    console.log(partial); // { name: '林萃', age: 20 }
    // 这种模式常用于创建对象类型的变体，例如将所有属性设置为可选或只读


    // 4、结合 typeof 使用
    // keyof可以与typeof一起使用，获取某个对象键的联合类型，常用于泛型函数中增强类型推断

    const settings = {
        theme: 'dark',
        version: '1.0',
        useCache: true
    }
    type SettingsKeys = keyof typeof settings; // "theme" | "version" | "useCache"
    // 创建一个映射类型，用于根据键名推断对应的值类型
    type SettingsValues = {
        [K in SettingsKeys]: typeof settings[K]
    }
    // 泛型函数，根据key的类型推断value的类型
    function updateSetting<K extends SettingsKeys>(key: K, value: SettingsValues[K]): SettingsValues[K] {
        // console.log(`Updating ${key} to ${value}`);
        return value
    }
    // 正确使用
    let theme = updateSetting("theme", 'light')
    let version = updateSetting("version", '2.0')
    let useCache = updateSetting("useCache", true)
    console.log(theme, version, useCache); // light 2.0 true


    // 实战案例

    // 1、增强对象类型的灵活性
    // 在设计Api接口或库的时候，keyof 可以帮助你创建更加灵活的函数和类型定义
    type APIResponse = {
        data: string
        error: string
    }

    type APIResponseKeys = keyof APIResponse; // // "data" | "error"

    function handleResponse(key: APIResponseKeys, response: APIResponse) {
        if (key === 'data') {
            console.log(response[key] as string);
        } else if (key === 'error') {
            console.log(response[key] as string);
        }
    }



    // 2、实现类型安全的字典
    // keyof 可以用于实现类型安全的字典或映射
    type UserRole = "admin" | "user" | "guest";

    type Permissions = {
        [role in UserRole]: string[]
    }

    const permissions: Permissions = {
        admin: ["create", "edit", "delete"],
        user: ["edit"],
        guest: []
    }

    function getPermissions(role: keyof Permissions): string[] {
        return permissions[role]
    }

    console.log(getPermissions("admin")); // [ 'create', 'edit', 'delete' ]
    console.log(getPermissions("user")); // [ 'edit' ]
    console.log(getPermissions("guest")); // []


    // 总结
    // keyof 的核心功能：获取对象类型的所有键，并将这些键组成一个联合类型
    // 常见应用：约束函数参数、动态属性访问、遍历对象属性、增强类型推断
    // 实际应用场景：设计灵活的函数接口、类型安全的字典、泛型编程等。
    // 通过巧妙使用keyof，你可以提升ts代码的类型安全性和灵活性，从而编写更加健壮和以维护的代码










}